/* Title:		
 *
 * Project:     related search keyword
 *
 * @ Link: 		http://...
 *
 * @ Email:		ivan_ling@hotmail.com
 *
 * @ Copyright: Copyright (c) 2008 pub
 *
 * @ Author 	Ivan.ling
 *
 * @ Version 	1.0
 
 * @ last change time 2008-01-20 	
 */
package com.pub.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class XMLUtils extends FileUtils
{
	private static WritableByteChannel fiOutChannel;
	private static ByteBuffer bbBuffer;
	
	private final byte BT_START_TAG = '<';
	private final byte BT_END_TAG = '>';
	private final byte BT_BACKSLASH_TAG = '/';
	
	private int iBufferSize;
	private String strPath;
	private Document doc;

	public static void main(String args[])
	{
		try {
			XMLUtils xu = new XMLUtils();
			
			DocumentBuilderFactory factory 	= DocumentBuilderFactory.newInstance();
			DocumentBuilder builder 		= factory.newDocumentBuilder();
			
	        Document doc = builder.newDocument();
	        
	        Element resultSet 	= doc.createElement("resultset");
	        xu.addElement(resultSet, "test");
	        
	        
			doc.setXmlVersion("1.0");
			doc.appendChild(resultSet);
			
			xu.buildXmlFile(doc, "e:/test_ivan.xml", "UTF-8");
			
			System.out.println("=====");
//			XMLUtils xu = new XMLUtils("testniocsv.csv", 1024);
//			xu.initNioWriter();
//			xu.addStartTag("products");
//			xu.addStartTag("product");
//			xu.addTag("pd", "12345", true);
//			
//			xu.addEndTag("product");
//			xu.addEndTag("products");
//			
//			xu.close();
//			Vector<Node> list;
			
//			Document doc = xu.parseXMLDocument("E:/mail.xml");
//			if(doc == null)
//				System.out.println("doc == null.");
//			else{
//				list = xu.getAllElement(doc, "Server");
//			
//				for(Node nd : list){
//					Map<String, String> data = xu.getNameTextContent(nd);
//					System.out.println("222222222222=====" + data.toString());
////					Node ndd = xu.getNode(nd, "NameKey");
////					if(ndd != null)
////						System.out.println("222222222222=====" + ndd.getTextContent());
//					
////					Vector<Node> nli = xu.getNodes(nd, "NameKey");
////					
////					for(Node nd1 : nli){
////						System.out.println("222222222222=====" + nd1.getNodeName());
////					}
//				}
				
//		        StringBuilder sbReceiveListTO  	= new StringBuilder(100);
//		        StringBuilder sbReceiveListCC  	= new StringBuilder(100);
//		        StringBuilder sbReceiveListBCC 	= new StringBuilder(100);
//		        StringBuilder sbAttachFileList	= new StringBuilder(100);
//		        Map<String, Map<String, String>> hmSendReceiveList = new HashMap<String, Map<String, String>>();
//		        
//		        
//				list = xu.getAllElement(doc, "SendReceive");
//				
//				for(Node nd : list){
//			        sbReceiveListTO 	= sbReceiveListTO.delete(0,sbReceiveListTO.length());		//-- initial to primary recipients mail address list
//			        sbReceiveListCC 	= sbReceiveListCC.delete(0,sbReceiveListCC.length());		//-- initial carbon copy recipients mail address list
//			        sbReceiveListBCC 	= sbReceiveListBCC.delete(0,sbReceiveListBCC.length());		//-- initial blind carbon copy recipients mail address list
//			        sbAttachFileList 	= sbAttachFileList.delete(0,sbAttachFileList.length());		//-- initial attach file name list
//
//			        Map<String, String> hmSendReceiveData = new HashMap<String, String>();
//			        
//					Vector<Node> data = xu.getElementNodes(nd);
//					for(Node ndData : data){
//						
//						
//						if(ndData.getNodeName().equalsIgnoreCase("ReceiveTO")){
//		            		if(Validate.isSimpleEmail(ndData.getTextContent())){
//			            		if(sbReceiveListTO.length() > 0)
//			            			sbReceiveListTO.append(",");
//			            		sbReceiveListTO.append(ndData.getTextContent());
//			            	}else
//			            		continue;	//-- add mail address error debug info 
//		            	}else if(ndData.getNodeName().equalsIgnoreCase("ReceiveCC")){
//		            		if(Validate.isSimpleEmail(ndData.getTextContent())){
//			            		if(sbReceiveListCC.length() > 0)
//			            			sbReceiveListCC.append(",");
//			            		sbReceiveListCC.append(ndData.getTextContent());
//			            	}else 
//			            		continue;	//-- add mail address error debug info 
//		            	}else if(ndData.getNodeName().equalsIgnoreCase("ReceiveBCC")){
//		            		if(Validate.isSimpleEmail(ndData.getTextContent())){
//			            		if(sbReceiveListBCC.length() > 0)
//			            			sbReceiveListBCC.append(",");
//			            		sbReceiveListBCC.append(ndData.getTextContent());
//			            	}else
//			            		continue;	//-- add mail address error debug info 
//		            	}else if(ndData.getNodeName().equalsIgnoreCase("Attach")){
//		            		if(sbAttachFileList.length() > 0)
//		            			sbAttachFileList.append(",");
//		            		sbAttachFileList.append(ndData.getTextContent());
//			            }else{
//		            		hmSendReceiveData.put(ndData.getNodeName(), ndData.getTextContent());
//			            }
//					}
//					
//					if(sbReceiveListTO.length() > 0)
//		            	hmSendReceiveData.put("ReceiveTO", sbReceiveListTO.toString());		//-- add receiveTO mail address list
//		            if(sbReceiveListCC.length() > 0)
//		            	hmSendReceiveData.put("ReceiveCC", sbReceiveListCC.toString());		//-- add receiveCC mail address list
//		            if(sbReceiveListBCC.length() > 0)
//		            	hmSendReceiveData.put("ReceiveBCC", sbReceiveListBCC.toString());	//-- add receiveBCC mail address list
//		            if(sbAttachFileList.length() > 0)
//		            	hmSendReceiveData.put("Attach", sbAttachFileList.toString());		//-- add attach file name list
//		            
//		            if(hmSendReceiveData.size() >0){
//		            	hmSendReceiveList.put(hmSendReceiveData.get("NameKey"), hmSendReceiveData);
//		            	System.out.println("hmSendReceiveList has put a element!" + hmSendReceiveData.get("NameKey"));
//		            	System.out.println("----------------------" + hmSendReceiveData.toString());
//		            }
//					
//				}
//			}
			//System.out.println(FileUtils.strZip("ReadMe.txt"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}			
	}
	
	public XMLUtils()
    {
    }
	
	public XMLUtils(String path)
    {
        this.strPath = path;
    }
   
	public XMLUtils(String strFileName, int iBufferLength)
    {
		this.strPath 		= strFileName;
		this.iBufferSize 	= iBufferLength;
    }
	
	public void initNioWriter() throws FileNotFoundException
	{
		File fiFile = new File(this.strPath);  
	    FileOutputStream outputFile = null;
	    
	    outputFile = new FileOutputStream(fiFile);
	    
	    XMLUtils.fiOutChannel 	= Channels.newChannel(outputFile);
	    XMLUtils.bbBuffer 		= ByteBuffer.allocate(this.iBufferSize);
	}
	
	public Document init()
    {
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        
        Document doc = null;
        try
        {
            DocumentBuilder builder=factory.newDocumentBuilder();
            
            doc = builder.newDocument();
        }catch(ParserConfigurationException e){
           e.printStackTrace();
        }
        
        return doc;
    }
   
    public void addTag(String tagName, String value, boolean isAddEndTag) throws IOException
    {
    	XMLUtils.bbBuffer.put(BT_START_TAG);
    	XMLUtils.bbBuffer.put(tagName.getBytes());
    	XMLUtils.bbBuffer.put(BT_END_TAG);
    	XMLUtils.bbBuffer.put(value.getBytes());
     	if(isAddEndTag){
    		XMLUtils.bbBuffer.put(BT_START_TAG);
    		XMLUtils.bbBuffer.put(BT_BACKSLASH_TAG);
     		XMLUtils.bbBuffer.put(tagName.getBytes());
    		XMLUtils.bbBuffer.put(BT_END_TAG);
    	}
    	
    	XMLUtils.bbBuffer.flip();
   		XMLUtils.fiOutChannel.write(XMLUtils.bbBuffer);
    	XMLUtils.bbBuffer.clear();
    }
    
    public void addEndTag(String tagName) throws IOException
    {
    	XMLUtils.bbBuffer.put(BT_START_TAG);
 		XMLUtils.bbBuffer.put(BT_BACKSLASH_TAG);
		XMLUtils.bbBuffer.put(tagName.getBytes());
		XMLUtils.bbBuffer.put(BT_END_TAG);
		
		XMLUtils.bbBuffer.flip();
		XMLUtils.fiOutChannel.write(XMLUtils.bbBuffer);
		XMLUtils.bbBuffer.clear();
    }
    
    public void addStartTag(String tagName) throws IOException
    {
    	XMLUtils.bbBuffer.put(BT_START_TAG);
 		XMLUtils.bbBuffer.put(tagName.getBytes());
		XMLUtils.bbBuffer.put(BT_END_TAG);
		
		XMLUtils.bbBuffer.flip();
		XMLUtils.fiOutChannel.write(XMLUtils.bbBuffer);
    	XMLUtils.bbBuffer.clear();
    }
    
    public void close() throws IOException
    {
    	XMLUtils.fiOutChannel.close();
    }
    
    public Element createRootElement(String rootTagName)
    {    
        if(doc.getDocumentElement()==null)
        {
            Element root = doc.createElement(rootTagName);
            doc.appendChild(root);
            
            return root;
        }
        
        return doc.getDocumentElement();
    }
   
     public Element createElement(Element parent, String tagName)
    {
        Document doc=parent.getOwnerDocument();
        Element child=doc.createElement(tagName);
        parent.appendChild(child);       
        
        return child;
    }
   
   public Element createElement(Element parent,String tagName,String value)
    {
        Document doc=parent.getOwnerDocument();
        Element child=doc.createElement(tagName);
        setElementValue(child,value);
        parent.appendChild(child);
        
        return child;
    }
   
    public void createAttribute(Element parent,String attrName,String attrValue)
    {
    	setElementAttr(parent,attrName,attrValue);       
    }
   
    public void buildXmlFile(String strEncoding) throws TransformerException
    {
        TransformerFactory tfactory=TransformerFactory.newInstance();
 
        Transformer transformer=tfactory.newTransformer();
        DOMSource source=new DOMSource(doc);
        
        StreamResult result=new StreamResult(new File(this.strPath));
        
        transformer.setOutputProperty(OutputKeys.ENCODING, strEncoding);
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        
        transformer.transform(source,result);
    }
   
    public Document getDoc()
    {
        return this.doc;
    }
    
    public void setDoc(Document doc)
    {
        this.doc = doc;
    }

    public String getPath()
    {
        return this.strPath;
    }
    
    public void setPath(String path)
    {
        this.strPath = path;
    }
 
     public NodeList getNodeList(Element parent)
     {
         return parent.getChildNodes();
     }
    
     public NodeList getNodeList(Node parent)
     {
         return parent.getChildNodes();
     }
     
     public Element [] getElements(Element parent, String name)
     {
         ArrayList<Node> resList = new ArrayList<Node>();
         NodeList nl=getNodeList(parent);
         for(int i=0;i<nl.getLength();i++)
         {
             Node nd=nl.item(i);
             if(nd.getNodeName().equals(name))
             {
                 resList.add(nd);
             }
         }
         Element [] res=new Element [resList.size()];
         for(int i=0;i<resList.size();i++)
         {
             res[0]=(Element)resList.get(i);
         }       
  
         return res;
     }
     
     public Vector<Node> getNodes(Node parent)
     {
         Vector<Node> resList = new Vector<Node>();
         NodeList nl = getNodeList(parent);
         for(int i = 0; i < nl.getLength(); i++)
         {
             resList.add(nl.item(i));
         }
   
         return resList;
     }
    
     public Vector<Node> getElementNodes(Node parent)
     {
         Vector<Node> resList = new Vector<Node>();
         NodeList nl = getNodeList(parent);
         for(int i = 0; i < nl.getLength(); i++)
         {
        	 if(nl.item(i).getNodeType() == Node.ELEMENT_NODE)
        		 resList.add(nl.item(i));
         }
   
         return resList;
     }
     
     public Map<String, String> getNameTextContent(Node parent)
     {
         Map<String, String> resList = new HashMap<String, String>();
         NodeList nl = getNodeList(parent);
         int len = nl.getLength();
         for(int i = 0; i < len; i++)
         {
             if(nl.item(i).getNodeType() == Node.ELEMENT_NODE)
            	 resList.put(nl.item(i).getNodeName(), nl.item(i).getTextContent());
         }
   
         return resList;
     }
     
     public Vector<Node> getNodes(Node parent, String name)
     {
         Vector<Node> resList = new Vector<Node>();
         NodeList nl = getNodeList(parent);
         for(int i = 0; i < nl.getLength(); i++)
         {
             Node nd = nl.item(i);
             if(nd.getNodeName().equals(name))
             {
                 resList.add(nd);
             }
         }
   
         return resList;
     }
     
     public Node getNode(Node parent, String name)
     {
         NodeList nl = getNodeList(parent);
         for(int i = 0; i < nl.getLength(); i++)
         {
             Node nd=nl.item(i);
             if(nd.getNodeName().equals(name))
             {
                 return nd;
             }
         }
   
         return null;
     }
     
     public Vector<Node> getAllElement(Node node, String nodeName)
     {
    	 Node nd;
    	 Vector<Node> vecReturn = new Vector<Node>();
    	 
    	 Stack<Node> stack = new Stack<Node>();
    	 stack.push(node);
    	 
    	 while(!stack.empty()){
    		 nd = stack.pop();
    		 //System.out.println("================= " + nd.getNodeName());
    		 if(nd.getNodeName() != null && nd.getNodeName().equals(nodeName)){
    			 vecReturn.add(nd);
//    			 
//        		 System.out.println("name = " + nodeName);
//        		 System.out.println("TEXT_NODE = " + nd.getNodeType());
             }
    		 
	    	 NodeList children = nd.getChildNodes();
	    	 if(children != null){
	    		 int len = children.getLength();
	    		 for(int i = 0; i < len; i++){
	    			 nd = children.item(i);
	    			 
	    			 stack.push(nd);
	    		 }
	    	 }
    	 }
    	 
    	 return vecReturn;
     }
     
     public String getElementName(Element element)
     {
         return element.getNodeName();
     }
    
     public String getElementValue(Element element)
     {
         NodeList nl=element.getChildNodes();
         for(int i=0;i<nl.getLength();i++)
         {
             if(nl.item(i).getNodeType()==Node.TEXT_NODE)//Text Node
             {           
                 return element.getFirstChild().getNodeValue();
             }
         }  
  
         return null;
     }
    
     public String getElementAttr(Element element, String attr)
     {
         return element.getAttribute(attr);
     }
    
      public void setElementValue(Element element, String val)
     {
         Node node=element.getOwnerDocument().createTextNode(val);
         NodeList nl=element.getChildNodes();
         for(int i=0;i<nl.getLength();i++)
         {
             Node nd=nl.item(i);
             if(nd.getNodeType()==Node.TEXT_NODE)//Text Node
             {           
            	 nd.setNodeValue(val);
                 return;
             }
         }  
 
         element.appendChild(node);       
     }
    
     public void setElementAttr(Element element, String attr, String attrVal)
     {
         element.setAttribute(attr,attrVal);
     }
    
     public void addElement(Element parent,Element child)
     {
         parent.appendChild(child);
     }
    
     public Element addElement(Element parent,String tagName)
     {       
         Document doc  = parent.getOwnerDocument();
         Element child = doc.createElement(tagName);
         parent.appendChild(child);
         
         return child;
     }
    
     public void addElement(Element parent,String tagName,String text)
     {
         Document doc=parent.getOwnerDocument();
         Element child=doc.createElement(tagName);
         setElementValue(child,text);
         parent.appendChild(child);
     }
    
     public void removeElement(Element parent,String tagName)
     {
         NodeList nl=parent.getChildNodes();
         for(int i=0;i<nl.getLength();i++)
         {
             Node nd=nl.item(i);
             if(nd.getNodeName().equals(tagName))
             {
                 parent.removeChild(nd);
             }
         }
      }
     
    
	/**
     * @param  path : file path
     * @param  strEncoding: document encoding
	 * @throws TransformerException 
	 * @throws ParserConfigurationException 
    **/
    public void buildXmlFile(Document doc, String path, String strEncoding) throws TransformerException, ParserConfigurationException
    {
        TransformerFactory tfactory = TransformerFactory.newInstance();
        tfactory.setAttribute("indent-number", new Integer(2));
        
        Transformer transformer = tfactory.newTransformer();
        DOMSource source = new DOMSource(doc);
       
        StreamResult result = new StreamResult(new File(path));
        
        transformer.setOutputProperty(OutputKeys.ENCODING, strEncoding);
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        
        transformer.transform(source,result);
     }
	    
	/**
	 * initialize Document
	 * @return a Document
	 * @throws ParserConfigurationException 
	 */
	public Document newXMLDocument() throws ParserConfigurationException 
	{
		return newDocumentBuilder().newDocument();
	}

	/**
	 * initialize DocumentBuilder
	 * @return a DocumentBuilder
	 * @throws ParserConfigurationException
	 */
	public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException 
	{
		return newDocumentBuilderFactory().newDocumentBuilder();
	}

	/**
	 * initialize DocumentBuilderFactory
	 * @return a DocumentBuilderFactory
	 */
	public DocumentBuilderFactory newDocumentBuilderFactory() 
	{
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		
		return dbf;
	} 
	
	/**
	 * with XML String, return org.w3c.dom.Document object.
	 * @param  xmlString 一个符合XML规范的字符串表达。
	 * @return a Document
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 * @throws SAXException 
	 */
	public Document parseXMLDocumentByString(String xmlString) throws SAXException, IOException, ParserConfigurationException 
	{
		if (xmlString == null) {
			throw new IllegalArgumentException();
		}
		
		return newDocumentBuilder().parse(new InputSource(new StringReader(xmlString)));
	}

	/**
	* with input stream ，return org.w3c.dom.Document object.
	* @param input
	* @return a org.w3c.dom.Document
	* @throws ParserConfigurationException 
	* @throws IOException 
	* @throws SAXException 
	*/
	public Document parseXMLDocumentByInputStream(InputStream input) throws SAXException, IOException, ParserConfigurationException
	{
		if (input == null) {
			throw new IllegalArgumentException("parameter is null !");
		}
	
		return newDocumentBuilder().parse(input);
	}
	
	/**
	 * with file name, return org.w3c.dom.Document object.
	 * @param fileName
	 * @return a org.w3c.dom.Document
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 * @throws SAXException 
	 */
	public Document parseXMLDocument(String fileName) throws SAXException, IOException, ParserConfigurationException {
		if (fileName == null) {
			throw new IllegalArgumentException("parameter is null !");
		}
		
		File fiNewFile = new File(fileName);
		if(!fiNewFile.isFile() && fiNewFile.createNewFile())
			return newDocumentBuilder().parse(fiNewFile);
		else
			return newDocumentBuilder().parse(fiNewFile);
	}
	
	/**
	 * with, return Document object.
	 * @param node a Document node
	 * @return a new Document
	 * @throws ParserConfigurationException 
	 */
	public Document newXMLDocumentByNode(Node node) throws ParserConfigurationException
	{
		Document doc = newXMLDocument();
		doc.appendChild(doc.importNode(node, true));
		
		return doc;
	} 
	
	public static String XMLParse(Document docDoc, String strTag)
    {
		NodeList nlChildNodeCache = docDoc.getElementsByTagName(strTag);;
		if(nlChildNodeCache != null && nlChildNodeCache.getLength() > 0){
			Node nodCache = nlChildNodeCache.item(0);
			return nodCache.getFirstChild().getNodeValue();
		}
	
		return null;
    }
	
	public static Document getDocument(URLConnection connUrl) throws SAXException, IOException, ParserConfigurationException
    {
    	connUrl.connect();
    	InputStream inDataStream = connUrl.getInputStream();
    	
    	Document 	docDoc;
    	DocumentBuilderFactory dbfDocFactory = DocumentBuilderFactory.newInstance(); 
		DocumentBuilder dbDocBuilder = dbfDocFactory.newDocumentBuilder();
		
		docDoc = dbDocBuilder.parse(inDataStream);
		
		inDataStream.close();
		return docDoc;
    }
	
	public static Document getDocument(HttpURLConnection connUrl) throws SAXException, IOException, ParserConfigurationException
    {
    	connUrl.connect();
    	InputStream inDataStream = connUrl.getInputStream();
    	
    	Document 	docDoc;
    	DocumentBuilderFactory dbfDocFactory = DocumentBuilderFactory.newInstance(); 
		DocumentBuilder dbDocBuilder = dbfDocFactory.newDocumentBuilder();
		
		docDoc = dbDocBuilder.parse(inDataStream);
		
		inDataStream.close();
		return docDoc;
    }
	
	/* get title data from xml document
	 * 
	 * @docDoc				XML document
	 * @strKeyTag			name of tag for HashMap key
	 * @strKeyAttriTag		name of attribute for key tag, if strKeyAttriTag is null, than key is value of tag.
	 * @strValueTag			name of tag for HashMap value.
	 * @strValueAttriTag	name of attribute for value tag, if strValueAttriTag is null, than value is value of tag.
	 *
	 */
	public static Map<String, String> getTitleData(Document docDoc, String strKeyTag, String strKeyAttriTag, String strValueTag, String strValueAttriTag)
	{
		Map<String, String> hmReturn = new HashMap<String, String>(24);
		
		NodeList nlColumnNode = docDoc.getElementsByTagName(strKeyTag);
		NodeList nlDataNode;
		int iDataNodeCount;
		
		if(nlColumnNode != null && nlColumnNode.getLength() > 0){
			int iColumnNum = nlColumnNode.getLength();
			Node nodCache;
			String strKeyCache;
			
			for (int i = 0; i < iColumnNum; i++){
				nodCache = nlColumnNode.item(i);
				
				if(strKeyAttriTag == null){
					strKeyCache = nodCache.getTextContent();
				}else{
					strKeyCache = nodCache.getAttributes().getNamedItem(strKeyAttriTag).getNodeValue();
				}
				
				nlDataNode 		= nodCache.getChildNodes();
				iDataNodeCount 	= nlDataNode.getLength();
				for (int j = 0; j < iDataNodeCount; j++){
					nodCache = nlDataNode.item(j);
					
					if(strValueAttriTag == null){
						if(nodCache.getNodeName().equals(strValueTag)){
							hmReturn.put(nodCache.getTextContent(), strKeyCache);
						}
					}else{
						hmReturn.put(nodCache.getAttributes().getNamedItem(strKeyAttriTag).getNodeValue(), strKeyCache);
					}
				}
			}
		}
		
		return hmReturn;
	}
	
	/* get data content from xml document
	 * 
	 * @docDoc				XML document
	 * @strKeyTag			name of tag for HashMap key
	 * @strKeyAttriTag		name of attribute for key tag, if strKeyAttriTag is null, than key is value of tag.
	 * @strValueTag			name of tag for HashMap value.
	 * @strValueAttriTag	name of attribute for value tag, if strValueAttriTag is null, than value is value of tag.
	 *
	 */
	@SuppressWarnings("unchecked")
	public static ArrayList<Map<String, String>> getData(Document docDoc, String strRowTag, String strKeyTag, String strKeyAttriTag, String strValueTag, String strValueAttriTag)
	{
		ArrayList<Map<String, String>> alReturn = new ArrayList<Map<String, String>>(20);
		
		NodeList nlRowNodeItems = docDoc.getElementsByTagName(strRowTag);
		NodeList nlColumnNode, nlDataNode;
		
		if(nlRowNodeItems != null && nlRowNodeItems.getLength() > 0){
			int iColumnNodeCount, iDataNodeCount;
			int iRowNodeCount = nlRowNodeItems.getLength();
			
			Node nodCache;
			HashMap<String, String> hmTpl = new HashMap<String, String>(24);
			HashMap<String, String> hmCache;
			
			String strKeyCache;
			
			for (int i = 0; i < iRowNodeCount; i++){
				nodCache = nlRowNodeItems.item(i);
				hmCache = (HashMap<String, String>)hmTpl.clone();
				
				nlColumnNode 	= nodCache.getChildNodes();
				iColumnNodeCount 	= nlColumnNode.getLength();
				for (int j = 0; j < iColumnNodeCount; j++){
					nodCache = nlColumnNode.item(j);
					
					if(nodCache.getNodeName().equals(strKeyTag)){
						if(strKeyAttriTag == null){
							strKeyCache = nodCache.getTextContent();
						}else{
							strKeyCache = nodCache.getAttributes().getNamedItem(strKeyAttriTag).getNodeValue();
						}
	
						nlDataNode 		= nodCache.getChildNodes();
						iDataNodeCount 	= nlDataNode.getLength();
						for (int k = 0; k < iDataNodeCount; k++){
							nodCache = nlDataNode.item(k);
						
						}
						if(strValueAttriTag == null){
							if(nodCache.getNodeName().equals("data")){
								hmCache.put(strKeyCache, nodCache.getTextContent());
							}
						}else{
							hmCache.put(strKeyCache, nodCache.getAttributes().getNamedItem(strKeyAttriTag).getNodeValue());
						}
					}
				}
				
				if(hmCache.size() > 0)
					alReturn.add(hmCache);
			}
		}
		return alReturn;
	}
	
	/* get data content from xml document
	 * 
	 * @docDoc				XML document
	 * @strKeyTag			name of tag for HashMap key
	 * @strKeyAttriTag		name of attribute for key tag, if strKeyAttriTag is null, than key is value of tag.
	 * @strValueTag			name of tag for HashMap value.
	 * @strValueAttriTag	name of attribute for value tag, if strValueAttriTag is null, than value is value of tag.
	 *
	 */
	@SuppressWarnings("unchecked")
	public static ArrayList<Map<String, String>> getData(Document docDoc, String strRowTag) throws UnsupportedEncodingException, DOMException
	{
		ArrayList<Map<String, String>> alReturn = new ArrayList<Map<String, String>>(20);
		
		NodeList nlRowNodeItems = docDoc.getElementsByTagName(strRowTag);
		NamedNodeMap nnmArribute;
		
		if(nlRowNodeItems != null && nlRowNodeItems.getLength() > 0){
			int iColumnNodeCount;
			int iRowNodeCount = nlRowNodeItems.getLength();
			
			Node nodCache;
			HashMap<String, String> hmTpl = new HashMap<String, String>(24);
			HashMap<String, String> hmCache;
			
			for (int i = 0; i < iRowNodeCount; i++){
				nodCache = nlRowNodeItems.item(i);
				hmCache = (HashMap<String, String>)hmTpl.clone();
				
				hmCache.put(nodCache.getNodeName(), new String(nodCache.getTextContent().getBytes(docDoc.getXmlEncoding()), "ISO8859-1"));
				
				nnmArribute 		= nodCache.getAttributes();
				iColumnNodeCount 	= nnmArribute.getLength();
				for (int j = 0; j < iColumnNodeCount; j++){
					nodCache = nnmArribute.item(j);
					
					hmCache.put(nodCache.getNodeName(), new String(nodCache.getTextContent().getBytes(docDoc.getXmlEncoding()), "ISO8859-1"));
				}
				
				if(hmCache.size() > 0)
					alReturn.add(hmCache);
			}
		}
		return alReturn;
	}
	
    public Comment addComment(String comment)
    {
    	Comment cmNode = null;
    	
    	if(doc != null){
    		cmNode = doc.createComment(comment);
    		
    		doc.appendChild(cmNode);
    	}
    	
    	return cmNode;
    }
    
    public OutputStream buildXml(OutputStream outputStream) throws TransformerException
    {
        TransformerFactory tfactory=TransformerFactory.newInstance();
 
        Transformer transformer=tfactory.newTransformer();
        DOMSource source 	= new DOMSource(doc);
        StreamResult result = new StreamResult(outputStream);
        
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
       
        transformer.transform(source,result);
        
        return outputStream;
    }
}